#include <iostream>
#include <fstream>
#include <cstdio>
#include <json/json.h>
#include "spline.h"

using namespace std;

class F : public Function
{
public:
  double operator()(const double& x) const {return 1 / (1 + 25 * x * x);}
  double derivative(const double& x) const {return -50 * x / (1 + 25 * x * x) / (1 + 25 * x * x);}
  double sec_derivative(const double& x) const {return 50 * (75 * x * x - 1) / pow(1 + 25 * x * x, 3);}
}f;

double mx[100];
int main()
{
  ifstream ifs("A.json", std::ios::binary);
  Json::Reader reader;
  Json::Value obj;
  reader.parse(ifs, obj);
  //cout << " name " << obj["L"].asDouble() << endl;
  double L = obj["L"].asDouble();
  double R = obj["R"].asDouble();
  double cond = obj["condition"].asInt();
  double ord = obj["order"].asInt();

  FILE* file = nullptr;
  if (freopen_s(&file, "../data/A.out", "w", stdout) != 0) cerr << "error: File opening failure" << endl, exit(-1);
  for (double X = -1;X <= 1;X += 0.001) printf("%lf,", f(X));
  printf("%lf,", f(1));puts("");
  for (int i = 0;i < obj["n"].size();i++)
    {
      vector<double> x;
      for (int j = 0;j < obj["n"][i].asInt();j++) x.push_back(L + (R - L) / (obj["n"][i].asInt() - 1) * j);
      ppForm_interpolation line(f, x, ord, cond);
      line.solve();
      for (double X = -1;X <= 1;X += 0.001) printf("%lf,", line(X)), mx[i] = max(mx[i], fabs(f(X) - line(X)));
      printf("%lf,", line(1));
      mx[i] = max(mx[i], fabs(f(1) - line(1)));
      puts("");
    }
  fclose(stdout);

  if (freopen_s(&file, "../data/A2.out", "w", stdout) != 0) cerr << "error: File opening failure" << endl, exit(-1);
  for (int i = 0;i < obj["n"].size();i++)
    printf("%d,", obj["n"][i].asInt());
  puts("");
  for (int i = 0;i < obj["n"].size();i++)
    printf("%.10lf,", mx[i]);
  fclose(stdout);

  if (freopen_s(&file, "../data/A3.out", "w", stdout) != 0) cerr << "error: File opening failure" << endl, exit(-1); 
  for (int i = 1;i < obj["n"].size();i++)
    printf("%d,", i);
  puts("");
  for (int i = 1;i < obj["n"].size();i++)
    printf("%.10lf,", mx[i - 1] / mx[i]);
  fclose(stdout);
  return 0;
}
